#ifndef _INTERF_UTIL_H_
#define _INTERF_UTIL_H_

#include <resip/stack/TransactionMessage.hxx>
#include <rutil/Fifo.hxx>

using namespace resip;

class AS_Event
{
private:
	resip::SipStack& _stack;

public:
	SipMessagePtr _msg;

public:
	AS_Event(resip::SipStack& stack);
// 	AS_Event();
	virtual ~AS_Event();

public:
	void Recv(resip::SipMessage* pMsg);
	void Recv(BYTE* pBuffer);
	void Send(const SipMessagePtr& pMsg);
// 	void Ack(const SipMessagePtr& pMsg);
};
PTR_DEF(AS_Event);

//Please notice that, IT'S NOT PROCESS!!!
struct IProcessor
	: public IBase
{
	static IProcessorPtr New(const UINT32& processorNumber);

	virtual void push(const AS_EventPtr& event) = 0;
};

struct IParallelWork
	: public IBase
{
	static IParallelWorkPtr New();

	virtual void submit(const IWorkPtr& work) = 0;
};

struct IWork
	: public IBase
{
	virtual bool init() = 0;
	virtual bool cycle() = 0;
	virtual void destroy() = 0;
	virtual void cancelWait() = 0;
};

struct IThreadPool
	: public IBase
{
	static IThreadPoolPtr New();

	virtual void submit(const e::sys::IRunnablePtr& runnable) = 0;
};

struct ISqlExecutor
	: public IBase
{
	static ISqlExecutorPtr New(
		const e::db::IConnectionPoolPtr& dbPool,
		const e::String& dumpFileName = "sql-executer.sql",
		const e::String& name = "sql-executer",
		UINT32 threadCount = 2,
		UINT32 failRetryTimeout = 3);

	virtual UINT32 getQueueSize() const = 0;

	virtual void execute(
		const e::String& sql,
		const VoidPtr& execLock = VoidPtr()
		) = 0;
};

//////////////////////////////////////////////////////////////////////////
template<typename T>
class FifoQueue : public IBase {
public:
	typedef T DataType;
	typedef boost::shared_ptr<DataType> DataPtr;

	typedef std::list<DataPtr> Queue;

private:
	Queue _queue;
	e::sys::Mutex _mutex;
	e::sys::SyncPoint _sPoint;
	UINT32 _size;

public:
	FifoQueue():_size(0) {

	}

	~FifoQueue() {
		clear();
	} 

	void clear() {
		e::sys::ScopedLock lock(_mutex);
		_queue.clear();
		_size = 0;
	}

	UINT32 size() const {
		return _size;
	}

	void push(const DataPtr& node, bool doSignal = true) {
		{
			e::sys::ScopedLock lock(_mutex);
			_queue.push_back(node);
			_size ++;
		}
		if (doSignal) {
			_sPoint.signal();
		}
	}

	DataPtr pop(UINT32 timeout = 0) {
		DataPtr node = popData();
		if (node) {
			return node;
		}
		if (timeout > 0) {
			_sPoint.wait(timeout);
			return popData();
		} else {
			return DataPtr();
		}
	}

	void signal() {
		_sPoint.signal();
	}

private:
	DataPtr popData() {
		e::sys::ScopedLock lock(_mutex);
		if (_queue.empty()) {
			return DataPtr();
		}

		DataPtr node = _queue.front();
		_queue.pop_front();

		_size --;
		return node;
	}

};


//////////////////////////////////////////////////////////////////////////
//
class IODevice
	: public e::net::ISocketCallback
	, public boost::enable_shared_from_this<IODevice>
{
protected:
	e::net::ISocketPtr _fd;

public:
	IODevice();
	virtual ~IODevice();

	bool Init();
	void unInit();

public:
	void send(
		const SipMessagePtr& msg
		, e::net::Address to
		);
	void ack(
		const SipMessagePtr& msg
		, e::net::Address to
		);

protected:
	virtual void onSocketEvent(e::net::ISocketPtr socket, UINT32 event, e::ByteArray & sharedBuffer);
};
PTR_DEF(IODevice);

#endif